home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvitovdu / unix / c / tek4010vdu.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  13KB  |  504 lines

  1. /* Original Author:         Andrew Trevorrow
  2.    Implementation: Modula-2 under VAX/UNIX 4.2 BSD
  3.    Date Started:   June, 1986
  4.  
  5.    Description:
  6.    Implements the routines used in VDU-specific modules that emulate
  7.    a Tektronix 4010 terminal (VIS500/550, VT640).
  8.    The screen is assumed to be 780 pixels high by 1024 pixels wide.
  9.    (The actual resolution of an emulating screen may be different, but
  10.    such terminals provide automatic scaling.)
  11.    The bottom left pixel is the point (x=0,y=0); x coordinates
  12.    increase to the right and y coordinates increase up the screen.
  13.    DVItoVDU uses a coordinate scheme in which horizontal (=h) coordinates
  14.    also increase to the right but vertical (=v) coordinates increase DOWN the
  15.    screen, i.e. the top left pixel on the screen is the point (h=0,v=0).
  16.    This means that the Tektronix 4010 routines will have to do a
  17.    simple translation of the vertical coordinates passed by DVItoVDU.
  18.  
  19.    This version converted to C and ported to BSD and System V UNIX by
  20.    some chaps at Kernel Technology up to September 1989.  Contact
  21.    mjh@uk.co.kernel (Mark J. Hewitt) with bug fixes etc.
  22.  
  23.    Involved were:    Mark J. Hewitt
  24.                Dave Dixon
  25.             Marc Hadley
  26. */
  27.  
  28. #include "def.h"
  29.  
  30. static char *sccsid[] = "@(#)tek4010vdu.c    1.1";
  31.  
  32. unsigned int
  33.    maxy = 779;              /* TEK4010 vertical coordinates are in 0..maxy;
  34.                                some VDUs may change default value of 779     */
  35. unsigned int
  36.    lineht = 26;               /* height in TEK4010 pixels of a text line;
  37.                                some VDUs may change default value of 26      */
  38. unsigned int
  39.    dragdown ;               /*550 VDUs can use this value to drag
  40.                               Terse character baseline down to TeX ref pt   */
  41. short
  42.    havesentxy = 0x00;       /* don't need to send all 4 bytes of address?    */
  43.  
  44.  
  45. unsigned int  oldhiy;        /* for remembering old address in SendXYtek() */
  46. unsigned int  oldhix;
  47. unsigned int  oldloy;
  48.  
  49. unsigned int  charwidth = 13;    /* set by LoadFont and used in ShowChar */
  50. unsigned int  loadedsize = 0;    /* remember alpha size set by last LoadFont; VT640,
  51.                    VIS500/550 VDUs don't actually need to worry
  52.                    about this since they use non-TEK4010 fonts to
  53.                    draw in dialogue region. VIS240 however uses
  54.                    alpha mode font. */
  55. unsigned int  charsize = 0;    /* used to select alpha character size */
  56.  
  57. /******************************************************************************/
  58.  
  59. void SendXYtek (x, y)
  60. unsigned int  x, y;
  61. {
  62.  
  63. /* Translates the given screen address into 4 bytes.
  64.    havesentxy is used to minimize the number of bytes sent: after the first
  65.    4 bytes have been sent, subsequent bytes that don't change need not be sent
  66.    (except for the low x byte which is always sent).
  67.    If the high x byte changes then the low y byte must also be sent.
  68. */
  69.  
  70.   unsigned int  hiy, loy, hix, lox;
  71.   short   sendhix;
  72.  
  73. /* we assume y is in [0..maxy] and x is in [0..1023] */
  74.   hiy = ((int) ' ') + (y / 32);
  75.   hix = ((int) ' ') + (x / 32);
  76.   loy = ((int) '`') + (y % 32);
  77.   lox = ((int) '@') + (x % 32);
  78.   if (havesentxy)
  79.   {
  80.     if (hiy != oldhiy)
  81.     {
  82.       Write ((char) hiy);
  83.       oldhiy = hiy;
  84.     }
  85.     sendhix = (hix != oldhix);
  86.     if ((loy != oldloy) || sendhix)
  87.     {
  88.       Write ((char) loy);
  89.       oldloy = loy;
  90.     }
  91.     if (sendhix)
  92.     {
  93.       Write ((char) hix);
  94.       oldhix = hix;
  95.     }
  96.     Write ((char) lox);
  97.   }
  98.   else                /* send first 4 bytes */
  99.   {
  100.     Write ((char) hiy);
  101.     oldhiy = hiy;
  102.     Write ((char) loy);
  103.     oldloy = loy;
  104.     Write ((char) hix);
  105.     oldhix = hix;
  106.     Write ((char) lox);
  107.     havesentxy = TRUE;
  108.   }
  109. /* SYSDEP: We assume XON/XOFF flow control is enabled to avoid data loss. */
  110. }
  111.  
  112. /******************************************************************************/
  113.  
  114. Void TEK4010StartText ()
  115. {
  116.  
  117. /* DVItoVDU will only call MoveToTextLine, ClearTextLine, ClearScreen and
  118.    ResetVDU while in text mode.
  119. */
  120.  
  121.   Write (US);
  122. }
  123.  
  124. /******************************************************************************/
  125.  
  126. Void TEK4010MoveToTextLine (line)
  127. unsigned int  line;
  128. {
  129.  
  130. /* Move cursor to start of given line using lineht.
  131.    At the end of this routine we must be in alpha mode and ready to display
  132.    characters in the default charsize.
  133. */
  134.  
  135.   Write (GS);            /* switch to graphics mode */
  136.   SendXYtek (0, maxy + 1 - (line * lineht));
  137.   Write (ESC);            /* reset alpha character size */
  138.   Write ('0');
  139.   charsize = 0;
  140.   charwidth = 13;
  141.   Write (US);            /* back to alpha mode */
  142. }
  143.  
  144. /******************************************************************************/
  145.  
  146. Void TEK4010ClearScreen ()
  147. {
  148.   Write (GS);            /* make sure we're in graphics mode */
  149.   Write (ESC);
  150.   Write (FF);            /* erase graphics and put in alpha mode */
  151.   havesentxy = FALSE;        /* ESC FF will home cursor */
  152.   charsize = 0;            /* ESC FF resets character size */
  153.   charwidth = 13;
  154. }
  155.  
  156. /******************************************************************************/
  157.  
  158. Void TEK4010StartGraphics ()
  159. {
  160.  
  161. /* DVItoVDU will only call LoadFont, ShowChar and ShowRectangle while
  162.    in graphics mode.
  163. */
  164.  
  165.   if (charsize != loadedsize)
  166.   {                /* graphics mode was interrupted */
  167.     charsize = loadedsize;
  168.     dragdown = (charsize + 1) * 5;/* used by VIS500/550 ShowChar */
  169.     Write (GS);
  170.     Write (ESC);
  171.     Write ((char) (((int) '0') + charsize));
  172.                 /* recall last LoadFont character size */
  173.   }
  174.   Write (GS);
  175.   havesentxy = FALSE;        /* safer to send all location bytes anew */
  176. }
  177.  
  178. /******************************************************************************/
  179.  
  180. /*ARGSUSED*/
  181. Void TEK4010LoadFont (fontname, fontsize, localmag, hscale, vscale)
  182.  
  183. char  fontname[];
  184. unsigned int  fontsize;
  185. float   localmag, hscale, vscale;
  186.  
  187. /* Use the given fontsize to select an appropriate character size
  188.    (based on horizontal scaling only!) for future ShowChar calls.
  189. */
  190. {
  191.   unsigned int  newsize;
  192.  
  193. /* convert fontsize into scaled screen pixels using localmag and hscale */
  194.   fontsize = (int) (((float) fontsize) * localmag * hscale + 0.5);
  195. /* Chooose one of the 4 alpha mode character sizes based on fontsize:
  196.    charsize    maxchars/line    relative size     fontsize range
  197.        0             80               x1               0..40
  198.        1             40               x2              41..80
  199.        2             26               x3              81..120
  200.        3             20               x4             121...
  201.    The fontsize ranges were chosen by trial and error.
  202. */
  203.   if (fontsize < 41)
  204.   {
  205.     newsize = 0;
  206.     charwidth = 13;        /* 1024/80 = 12.8 */
  207.   }
  208.   else
  209.     if (fontsize < 81)
  210.     {
  211.       newsize = 1;
  212.       charwidth = 26;        /* 1024/40 = 25.6 */
  213.     }
  214.     else
  215.       if (fontsize < 121)
  216.       {
  217.     newsize = 2;
  218.     charwidth = 40;        /* 1024/26 = 39.4 */
  219.       }
  220.       else
  221.       {
  222.     newsize = 3;
  223.     charwidth = 52;        /* 1024/20 = 51.2 */
  224.       }
  225.   loadedsize = newsize;        /* remember in case graphics mode is interrupted */
  226.   if (charsize != newsize)
  227.   {                /* change character size */
  228.     charsize = newsize;
  229.     Write (ESC);
  230.     Write ((char) (((int) '0') + charsize));
  231.   }
  232. /* Alpha character reference pts on some emulating VDUs (VIS500/550) are below
  233.    baselines to allow for descenders.
  234.    Such VDUs can use dragdown to drag baselines down to TeX reference pts
  235.    when calling ShowChar.
  236. */
  237.   dragdown = (charsize + 1) * 5;/* used by VIS500/550 ShowChar */
  238.   Write (GS);            /* must exit in graphics mode */
  239. }
  240.  
  241. /******************************************************************************/
  242.  
  243. Void TEK4010ShowChar (screenh, screenv, ch)
  244. unsigned int  screenh, screenv;
  245. char  ch;
  246. /* Show the given Terse character (mapped to ASCII) at the given ref pt.
  247.    We use the charwidth set by last LoadFont call.
  248. */
  249. {
  250.   char  newch;            /* = TeXtoASCII[ch] */
  251.  
  252. /* shift character left if it will overlap right edge of screen */
  253.   if ((screenh + charwidth) > 1023)
  254.   {
  255.     screenh = 1023 - charwidth;
  256.   }
  257. /* we assume StartGraphics, LoadFont or last ShowChar has just sent GS */
  258.   SendXYtek (screenh, maxy - screenv);/* move cursor to ref pt */
  259.  
  260. /* We use TeXtoASCII to map ch into a comparable ASCII character, apart
  261.    from most of the ? characters which we attempt to simulate.
  262. */
  263.  
  264.   Write (US);            /* enter alpha mode */
  265.   newch = TeXtoASCII[ch];
  266.   if (newch != '?')
  267.   {
  268.   /* newch is similar to TeX ch */
  269.     Write (newch);
  270.   }
  271.   else
  272.   {                /* attempt to display something other than ? */
  273.     switch (ch)
  274.     {
  275.       case 013: 
  276.       case 014: 
  277.       case 015: 
  278.       case 016: 
  279.       case 017:  /* ff, fi, fl, ffi, ffl */ ;
  280.     {
  281.       Write ('f');
  282.     /* only simulate rest of ligature if room at right edge */
  283.       if ((screenh + 2 * charwidth - (charwidth / 2)) <= 1023)
  284.       {
  285.         Write (GS);
  286.         SendXYtek (screenh + charwidth - (charwidth / 2), maxy - screenv);
  287.         Write (US);
  288.         switch (ch)
  289.         {
  290.           case 013: 
  291.         {
  292.           Write ('f');
  293.           break;
  294.         }
  295.           case 014: 
  296.         {
  297.           Write ('i');
  298.           break;
  299.         }
  300.           case 015: 
  301.         {
  302.           Write ('l');
  303.           break;
  304.         }
  305.           case 016: 
  306.           case 017: 
  307.         {
  308.           Write ('f');
  309.           if (screenh + 3 * charwidth - 2 * (charwidth / 2) <= 1023)
  310.           {
  311.             Write (GS);
  312.             SendXYtek (screenh + 2 * charwidth - 2 * (charwidth / 2), maxy - screenv);
  313.             Write (US);
  314.             if (ch == 016)
  315.               Write ('i');
  316.             else
  317.               Write ('l');
  318.           }
  319.         }
  320.         }
  321.       }
  322.       break;
  323.     }
  324.       case 031: 
  325.     {
  326.       Write ('B');
  327.       break;
  328.     }            /* German sharp S */
  329.       case 032: 
  330.       case 033: 
  331.       case 035: 
  332.       case 036:         /* diphthongs: ae, oe, AE, OE */
  333.     {
  334.       switch (ch)
  335.       {
  336.         case 032: 
  337.           {
  338.         Write ('a');
  339.         break;
  340.           }
  341.         case 033: 
  342.           {
  343.         Write ('o');
  344.         break;
  345.           }
  346.         case 035: 
  347.           {
  348.         Write ('A');
  349.         break;
  350.           }
  351.         case 036: 
  352.           {
  353.         Write ('O');
  354.         break;
  355.           }
  356.       }
  357.       if ((screenh + 2 * charwidth - (charwidth / 2)) <= 1023)
  358.       {
  359.         Write (GS);
  360.         SendXYtek (screenh + charwidth - (charwidth / 2), maxy - screenv);
  361.         Write (US);
  362.         switch (ch)
  363.         {
  364.           case 032: 
  365.           case 033: 
  366.         {
  367.           Write ('e');
  368.           break;
  369.         }
  370.           case 035: 
  371.           case 036: 
  372.         {
  373.           Write ('E');
  374.           break;
  375.         }
  376.         }
  377.       }
  378.       break;
  379.     }
  380.       case 034: 
  381.       case 037:         /* Scandinavian slashed o and O */
  382.     {
  383.       switch (ch)
  384.       {
  385.         case 034: 
  386.           {
  387.         Write ('o');
  388.         break;
  389.           }
  390.         case 037: 
  391.           {
  392.         Write ('O');
  393.         break;
  394.           }
  395.       }
  396.       Write (GS);
  397.       SendXYtek (screenh, maxy - screenv);/* overwrite */
  398.       Write (US);
  399.       Write ('/');
  400.       break;
  401.     }
  402.       case 040: 
  403.     {
  404.       Write ('\'');
  405.       break;
  406.     }            /* Polish suppressed l and L */
  407.       default: 
  408.     Write ('?');
  409.     }
  410.   }
  411.   Write (GS);            /* must exit in graphics mode */
  412. }
  413.  
  414. /******************************************************************************/
  415.  
  416. /*ARGSUSED*/
  417. Void TEK4010ShowRectangle (screenh, screenv,/* top left pixel */
  418.   width, height,        /* of rectangle */
  419.   ch)                /* black pixel */
  420. unsigned int  screenh, screenv, width, height;
  421. char  ch;
  422. /* Display the given rectangle (without using the given black pixel character).
  423.    DVItoVDU ensures that the top left position is visible and that the given
  424.    dimensions do not go beyond the window edges.
  425. */
  426. {
  427.  
  428.   unsigned int  i, endpt;
  429.  
  430. /* DVItoVDU ensures width and height > 0 */
  431.   if (height < width)
  432.   {
  433.   /* show row vectors */
  434.     endpt = screenh + width - 1;
  435.     for (i = 0; i <= height - 1; i++)
  436.     {
  437.       Write (GS);
  438.       SendXYtek (screenh, maxy - (screenv + i));/* move cursor to start of row */
  439.       SendXYtek (endpt, maxy - (screenv + i));/* draw vector to end of row */
  440.     }
  441.   }
  442.   else                /* show column vectors */
  443.   {
  444.     endpt = maxy - (screenv + height - 1);
  445.     for (i = 0; i <= width - 1; i++)
  446.     {
  447.       Write (GS);
  448.       SendXYtek (screenh + i, maxy - screenv);/* move cursor to start of column */
  449.       SendXYtek (screenh + i, endpt);/* draw vector to end of column */
  450.     }
  451.   }
  452. }
  453.  
  454. /******************************************************************************/
  455.  
  456. Void TEK4010ClearTextLine (line)
  457.  
  458. unsigned int  line;
  459. {
  460.   Write (CAN);            /* switch to Alphanumeric mode */
  461.   TEK4010MoveToTextLine (line);    /* move to start of line */
  462.   Write (ESC);
  463.   Write ('K');            /* erase to end of line */
  464. }
  465.  
  466. Void TEK4010ResetVDU ()
  467. {
  468.   Write (CAN);
  469. }
  470.  
  471. void InitTEK4010 ()
  472. {
  473.   DVIstatusl = 1;        /* DVItoVDU assumes top text line = 1 */
  474.   windowstatusl = 2;
  475.   messagel = 3;
  476.   commandl = 4;
  477.   bottoml = 33;            /* also number of text lines on VIS500 screen */
  478. /* The above values assume the VIS500 is in Alphanumeric mode;
  479.    the following values assume it is emulating a Tektronix 4010.
  480.    Note that windowv must be given a value using DVItoVDU's coordinate scheme
  481.    where top left pixel is (0,0).
  482. */
  483.   windowv = 92;            /* approx. height in TEK4010 pixels of 4 text lines;
  484.                    i.e. 4 * 780/34 */
  485.   windowh = 0;
  486.   windowht = 780 - windowv;
  487.   windowwd = 1024;
  488.  
  489.   MoveToTextLine = TEK4010MoveToTextLine;
  490.   ClearTextLine = TEK4010ClearTextLine;
  491.   ClearScreen = TEK4010ClearScreen;
  492.   StartText = TEK4010StartText;
  493.   StartGraphics = TEK4010StartGraphics;
  494.   LoadFont = TEK4010LoadFont;
  495.   ShowChar = TEK4010ShowChar;
  496.   ShowRectangle = TEK4010ShowRectangle;
  497.   ResetVDU = TEK4010ResetVDU;
  498.  
  499.   Write (GS);
  500.   Write (ESC);
  501.   Write ('@');            /* solid fill for rectangular draw and fill */
  502.   Write (CAN);
  503. }
  504.